home *** CD-ROM | disk | FTP | other *** search
-
- #include "WINGsP.h"
-
-
- typedef struct W_TabView {
- W_Class widgetClass;
- W_View *view;
-
- struct W_TabViewItem **items;
- int itemCount;
- int maxItems; /* size of items array, can be increased */
-
- int selectedItem;
- int firstVisible;
-
- int visibleTabs;
-
- WMFont *font;
-
- WMColor *lightGray;
- WMColor *tabColor;
-
- WMTabViewDelegate *delegate;
-
- short tabWidth;
- short tabHeight;
-
- struct {
- WMReliefType relief:4;
- WMTitlePosition titlePosition:4;
- WMTabViewTypes type:2;
-
- unsigned tabbed:1;
- unsigned dontFitAll:1;
- } flags;
- } TabView;
-
-
-
- #define DEFAULT_WIDTH 40
- #define DEFAULT_HEIGHT 40
-
- #define NORMAL_SIDE_OFFSET 8
- #define BUTTONED_SIDE_OFFSET 20
-
-
- static void destroyTabView(TabView *tPtr);
- static void paintTabView(TabView *tPtr);
-
-
- static void W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent);
-
- static void W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect);
-
- static void W_UnmapTabViewItem(WMTabViewItem *item);
-
- static void W_MapTabViewItem(WMTabViewItem *item);
-
- static WMView *W_TabViewItemView(WMTabViewItem *item);
-
- static void recalcTabWidth(TabView *tPtr);
-
-
- static void
- handleEvents(XEvent *event, void *data)
- {
- TabView *tPtr = (TabView*)data;
-
- CHECK_CLASS(data, WC_TabView);
-
- switch (event->type) {
- case Expose:
- if (event->xexpose.count!=0)
- break;
- paintTabView(tPtr);
- break;
-
- case ButtonPress:
- {
- WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
- event->xbutton.x,
- event->xbutton.y);
- if (item) {
- WMSelectTabViewItem(tPtr, item);
- } else if (tPtr->flags.dontFitAll) {
- int redraw;
- if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
- if (tPtr->firstVisible > 0) {
- redraw = 1;
- tPtr->firstVisible--;
- }
- } else if (event->xbutton.x - BUTTONED_SIDE_OFFSET
- > tPtr->visibleTabs*(tPtr->tabWidth-10)) {
-
- if (tPtr->firstVisible + tPtr->visibleTabs
- < tPtr->itemCount) {
- redraw = 1;
- tPtr->firstVisible++;
- }
- }
-
- if (redraw) {
- paintTabView(tPtr);
- }
- }
- }
- break;
-
- case DestroyNotify:
- destroyTabView(tPtr);
- break;
- }
- }
-
-
-
- WMTabView*
- WMCreateTabView(WMWidget *parent)
- {
- TabView *tPtr;
- WMScreen *scr = WMWidgetScreen(parent);
-
- tPtr = wmalloc(sizeof(TabView));
- memset(tPtr, 0, sizeof(TabView));
-
- tPtr->widgetClass = WC_TabView;
-
- tPtr->view = W_CreateView(W_VIEW(parent));
- if (!tPtr->view) {
- wfree(tPtr);
- return NULL;
- }
- tPtr->view->self = tPtr;
-
- tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
- tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
-
- tPtr->font = WMRetainFont(scr->normalFont);
-
- WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
- |ButtonPressMask, handleEvents, tPtr);
-
- WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
-
- tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
-
- return tPtr;
- }
-
-
- void
- WMSetTabViewDelegate(WMTabView *tPtr, WMTabViewDelegate *delegate)
- {
- tPtr->delegate = delegate;
- }
-
-
- void
- WMAddItemInTabView(WMTabView *tPtr, WMTabViewItem *item)
- {
- WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
- }
-
-
- void
- WMInsertItemInTabView(WMTabView *tPtr, int index, WMTabViewItem *item)
- {
- wassertr(W_TabViewItemView(item) != NULL);
-
- if (tPtr->maxItems == tPtr->itemCount) {
- WMTabViewItem **items;
-
- items = wrealloc(tPtr->items,
- sizeof(WMTabViewItem*) * (tPtr->maxItems + 10));
- memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem*) * 10);
- tPtr->items = items;
- tPtr->maxItems += 10;
- }
-
- if (index > tPtr->itemCount)
- index = tPtr->itemCount;
-
- if (index == 0 && tPtr->items[0]) {
- W_UnmapTabViewItem(tPtr->items[0]);
- }
-
- if (index < tPtr->itemCount) {
- memmove(&tPtr->items[index + 1], &tPtr->items[index],
- tPtr->itemCount - index);
- }
-
- tPtr->items[index] = item;
-
- tPtr->itemCount++;
-
- recalcTabWidth(tPtr);
-
- W_SetTabViewItemParent(item, tPtr);
-
- W_UnmapTabViewItem(item);
-
- W_ReparentView(W_TabViewItemView(item), tPtr->view, 1,
- tPtr->tabHeight + 1);
-
- W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
- tPtr->view->size.height - tPtr->tabHeight - 3);
-
- if (index == 0) {
- W_MapTabViewItem(item);
- }
- if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
- (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
- }
-
-
- void
- WMRemoveTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
- {
- int i;
-
- for (i = 0; i < tPtr->itemCount; i++) {
- if (tPtr->items[i] == item) {
- if (i < tPtr->itemCount - 1)
- memmove(&tPtr->items[i], &tPtr->items[i + 1],
- tPtr->itemCount - i - 1);
- else
- tPtr->items[i] = NULL;
-
- W_SetTabViewItemParent(item, NULL);
-
- tPtr->itemCount--;
- break;
- }
- }
- if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
- (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
- }
-
-
-
- static Bool
- isInside(int x, int y, int width, int height, int px, int py)
- {
- if (py >= y + height - 3 && py <= y + height
- && px >= x + py - (y + height - 3)
- && px <= x + width - (py - (y + height - 3))) {
-
- return True;
- }
- if (py >= y + 3 && py < y + height - 3
- && px >= x + 3 + ((y + 3) - py)*3/7
- && px <= x + width - 3 - ((y + 3) - py)*3/7) {
-
- return True;
- }
- if (py >= y && py < y + 3
- && px >= x + 7 + py - y
- && px <= x + width - 7 - (py - y)) {
-
- return True;
- }
- return False;
- }
-
-
- WMTabViewItem*
- WMTabViewItemAtPoint(WMTabView *tPtr, int x, int y)
- {
- int i;
- int offset;
- int count = tPtr->visibleTabs;
- int first = tPtr->firstVisible;
-
- if (tPtr->flags.dontFitAll) {
- offset = BUTTONED_SIDE_OFFSET;
-
- i = tPtr->selectedItem - tPtr->firstVisible;
- if (i >= 0 && i < tPtr->visibleTabs
- && isInside(offset + (tPtr->tabWidth-10)*i, 0, tPtr->tabWidth,
- tPtr->tabHeight, x, y)) {
- return tPtr->items[tPtr->selectedItem];
- }
- } else {
- offset = NORMAL_SIDE_OFFSET;
-
- i = tPtr->selectedItem;
- if (isInside(offset + (tPtr->tabWidth-10)*i, 0, tPtr->tabWidth,
- tPtr->tabHeight, x, y)) {
- return tPtr->items[i];
- }
- }
-
- for (i = 0; i < count; i++) {
- if (isInside(offset + (tPtr->tabWidth-10)*i, 0, tPtr->tabWidth,
- tPtr->tabHeight, x, y)) {
- return tPtr->items[i+first];
- }
- }
- return NULL;
- }
-
-
- void
- WMSelectFirstTabViewItem(WMTabView *tPtr)
- {
- WMSelectTabViewItemAtIndex(tPtr, 0);
- }
-
-
- void
- WMSelectLastTabViewItem(WMTabView *tPtr)
- {
- WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
- }
-
-
- void
- WMSelectNextTabViewItem(WMTabView *tPtr)
- {
- WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
- }
-
-
- void
- WMSelectPreviousTabViewItem(WMTabView *tPtr)
- {
- WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
- }
-
-
- WMTabViewItem*
- WMGetSelectedTabViewItem(WMTabView *tPtr)
- {
- return tPtr->items[tPtr->selectedItem];
- }
-
-
- void
- WMSelectTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
- {
- int i;
-
- for (i = 0; i < tPtr->itemCount; i++) {
- if (tPtr->items[i] == item) {
- WMSelectTabViewItemAtIndex(tPtr, i);
- break;
- }
- }
- }
-
-
- void
- WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index)
- {
- WMTabViewItem *item;
-
- if (index == tPtr->selectedItem)
- return;
-
- if (index < 0)
- index = 0;
- else if (index >= tPtr->itemCount)
- index = tPtr->itemCount - 1;
-
- item = tPtr->items[tPtr->selectedItem];
-
- if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
- if (!(*tPtr->delegate->shouldSelectItem)(tPtr->delegate, tPtr,
- tPtr->items[index]))
- return;
-
- if (tPtr->delegate && tPtr->delegate->willSelectItem)
- (*tPtr->delegate->willSelectItem)(tPtr->delegate, tPtr,
- tPtr->items[index]);
-
- W_UnmapTabViewItem(item);
-
-
- item = tPtr->items[index];
-
- W_MapTabViewItem(item);
-
- tPtr->selectedItem = index;
-
- if (tPtr->delegate && tPtr->delegate->didSelectItem)
- (*tPtr->delegate->didSelectItem)(tPtr->delegate, tPtr,
- tPtr->items[index]);
- }
-
-
- static void
- recalcTabWidth(TabView *tPtr)
- {
- int i;
- int twidth = W_VIEW(tPtr)->size.width;
- int width;
-
- tPtr->tabWidth = 0;
- for (i = 0; i < tPtr->itemCount; i++) {
- char *str = WMGetTabViewItemLabel(tPtr->items[i]);
-
- if (str) {
- width = WMWidthOfString(tPtr->font, str, strlen(str));
- if (width > tPtr->tabWidth)
- tPtr->tabWidth = width;
- }
- }
- tPtr->tabWidth += 30;
- if ((tPtr->tabWidth + 2) * tPtr->itemCount > twidth - 2*NORMAL_SIDE_OFFSET) {
- tPtr->flags.dontFitAll = 1;
- tPtr->firstVisible = 0;
- tPtr->visibleTabs = (twidth - 2*BUTTONED_SIDE_OFFSET) / (tPtr->tabWidth-10);
- } else {
- tPtr->flags.dontFitAll = 0;
- tPtr->firstVisible = 0;
- tPtr->visibleTabs = tPtr->itemCount;
- }
- }
-
-
- static void
- drawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
- unsigned int height)
- {
- Display *dpy = scr->display;
- GC bgc = WMColorGC(scr->black);
- GC wgc = WMColorGC(scr->white);
- GC dgc = WMColorGC(scr->darkGray);
-
- XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
-
- XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
- XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
-
- XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
- XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
- }
-
-
- static void
- drawTab(TabView *tPtr, Drawable d, int x, int y,
- unsigned width, unsigned height, Bool selected)
- {
- WMScreen *scr = W_VIEW(tPtr)->screen;
- Display *dpy = scr->display;
- GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
- GC black = WMColorGC(scr->black);
- GC dark = WMColorGC(scr->darkGray);
- GC light = WMColorGC(scr->gray);
- XPoint trap[8];
-
- trap[0].x = x + (selected ? 0 : 1);
- trap[0].y = y + height - (selected ? 0 : 1);
-
- trap[1].x = x + 3;
- trap[1].y = y + height - 3;
-
- trap[2].x = x + 10 - 3;
- trap[2].y = y + 3;
-
- trap[3].x = x + 10;
- trap[3].y = y;
-
- trap[4].x = x + width - 10;
- trap[4].y = y;
-
- trap[5].x = x + width - 10 + 3;
- trap[5].y = y + 3;
-
- trap[6].x = x + width - 3;
- trap[6].y = y + height - 3;
-
- trap[7].x = x + width - (selected ? 0 : 1);
- trap[7].y = y + height - (selected ? 0 : 1);
-
- XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8,
- Convex, CoordModeOrigin);
-
- XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
- XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
- XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
- XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
- XDrawLine(dpy, d, dark, trap[4].x, trap[4].y, trap[5].x, trap[5].y);
- XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
- XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
-
- XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white),
- trap[0].x, trap[0].y, trap[7].x, trap[7].y);
- }
-
-
- static void
- paintDot(TabView *tPtr, Drawable d, int x, int y)
- {
- WMScreen *scr = W_VIEW(tPtr)->screen;
- Display *dpy = scr->display;
- GC white = WMColorGC(scr->white);
- GC black = WMColorGC(scr->black);
-
- XFillRectangle(dpy, d, black, x, y, 2, 2);
- XDrawPoint(dpy, d, white, x, y);
- }
-
-
-
- static void
- paintTabView(TabView *tPtr)
- {
- Pixmap buffer;
- WMScreen *scr = W_VIEW(tPtr)->screen;
- Display *dpy = scr->display;
- GC white = WMColorGC(scr->white);
- int i;
- WMRect rect;
-
- if (tPtr->flags.type == WTTopTabsBevelBorder) {
- int count = tPtr->visibleTabs;
- int first = tPtr->firstVisible;
- int offs;
- int moreAtLeft;
- int moreAtRight;
- int selectedIsVisible;
-
- buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
- W_VIEW(tPtr)->size.width, tPtr->tabHeight,
- W_VIEW(tPtr)->screen->depth);
-
- XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
- 0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
-
- rect.pos.y = 2;
- if (tPtr->flags.dontFitAll) {
- rect.pos.x = 15 + BUTTONED_SIDE_OFFSET;
- offs = BUTTONED_SIDE_OFFSET;
- moreAtLeft = first > 0;
- moreAtRight = (first + count) < tPtr->itemCount;
- if (tPtr->selectedItem >= first
- && tPtr->selectedItem < first + count)
- selectedIsVisible = 1;
- else
- selectedIsVisible = 0;
- } else {
- rect.pos.x = 15 + NORMAL_SIDE_OFFSET;
- offs = NORMAL_SIDE_OFFSET;
- moreAtLeft = 0;
- moreAtRight = 0;
- selectedIsVisible = 1;
- }
- rect.size.width = tPtr->tabWidth;
- rect.size.height = tPtr->tabHeight;
-
- for (i = count - (moreAtRight ? 0 : 1);
- i >= (moreAtLeft ? -1 : 0); i--) {
- if (!selectedIsVisible || i != (tPtr->selectedItem-first)) {
- drawTab(tPtr, buffer, offs + (rect.size.width-10)*i, 0,
- rect.size.width, rect.size.height, False);
- }
- }
-
- if (selectedIsVisible) {
- drawTab(tPtr, buffer,
- offs + (rect.size.width-10) * (tPtr->selectedItem - first),
- 0, rect.size.width, rect.size.height, True);
-
- XDrawLine(dpy, buffer, white, 0, tPtr->tabHeight - 1,
- offs, tPtr->tabHeight - 1);
-
- XDrawLine(dpy, buffer, white,
- offs + 10 + (rect.size.width-10) * count,
- tPtr->tabHeight - 1, W_VIEW(tPtr)->size.width - 1,
- tPtr->tabHeight - 1);
- } else {
- XDrawLine(dpy, buffer, white, 0, tPtr->tabHeight - 1,
- W_VIEW(tPtr)->size.width, tPtr->tabHeight - 1);
- }
-
- for (i = 0; i < count; i++) {
- W_DrawLabel(tPtr->items[first+i], buffer, rect);
-
- rect.pos.x += rect.size.width - 10;
- }
-
- if (moreAtLeft) {
- paintDot(tPtr, buffer, 4, 10);
- paintDot(tPtr, buffer, 7, 10);
- paintDot(tPtr, buffer, 10, 10);
- }
- if (moreAtRight) {
- int x;
-
- x = BUTTONED_SIDE_OFFSET - 5 + tPtr->visibleTabs * (tPtr->tabWidth - 10);
-
- x = x + (W_VIEW(tPtr)->size.width - x)/2;
-
- paintDot(tPtr, buffer, x + 5, 10);
- paintDot(tPtr, buffer, x + 8, 10);
- paintDot(tPtr, buffer, x + 11, 10);
- }
-
- XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
- W_VIEW(tPtr)->size.width, tPtr->tabHeight, 0, 0);
-
- XFreePixmap(dpy, buffer);
- }
- switch (tPtr->flags.type) {
- case WTTopTabsBevelBorder:
- drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
- W_VIEW(tPtr)->size.width,
- W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
- break;
-
- case WTNoTabsBevelBorder:
- W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
- W_VIEW(tPtr)->size.height, WRRaised);
- break;
-
- case WTNoTabsLineBorder:
- W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
- W_VIEW(tPtr)->size.height, WRSimple);
- break;
-
- case WTNoTabsNoBorder:
- break;
- }
- }
-
-
- static void
- destroyTabView(TabView *tPtr)
- {
- int i;
-
- for (i = 0; i < tPtr->itemCount; i++) {
- WMSetTabViewItemView(tPtr->items[i], NULL);
- WMDestroyTabViewItem(tPtr->items[i]);
- }
- wfree(tPtr->items);
-
- WMReleaseColor(tPtr->lightGray);
- WMReleaseColor(tPtr->tabColor);
- WMReleaseFont(tPtr->font);
-
- wfree(tPtr);
- }
-
- /******************************************************************/
-
-
- typedef struct W_TabViewItem {
- WMTabView *tabView;
-
- W_View *view;
-
- char *label;
-
- int identifier;
-
- struct {
- unsigned visible:1;
- } flags;
- } TabViewItem;
-
-
- static void
- W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent)
- {
- item->tabView = parent;
- }
-
-
- static void
- W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect)
- {
- WMScreen *scr = W_VIEW(item->tabView)->screen;
-
- if (!item->label)
- return;
-
- WMDrawString(scr, d, WMColorGC(scr->black), item->tabView->font,
- rect.pos.x, rect.pos.y, item->label, strlen(item->label));
- }
-
-
- static void
- W_UnmapTabViewItem(WMTabViewItem *item)
- {
- wassertr(item->view);
-
- W_UnmapView(item->view);
-
- item->flags.visible = 0;
- }
-
-
- static void
- W_MapTabViewItem(WMTabViewItem *item)
- {
- wassertr(item->view);
-
- W_MapView(item->view);
-
- item->flags.visible = 1;
- }
-
-
- static WMView*
- W_TabViewItemView(WMTabViewItem *item)
- {
- return item->view;
- }
-
-
- WMTabViewItem*
- WMCreateTabViewItemWithIdentifier(int identifier)
- {
- WMTabViewItem *item;
-
- item = wmalloc(sizeof(WMTabViewItem));
- memset(item, 0, sizeof(WMTabViewItem));
-
- item->identifier = identifier;
-
- return item;
- }
-
-
- int
- WMGetTabViewItemIdentifier(WMTabViewItem *item)
- {
- return item->identifier;
- }
-
-
- void
- WMSetTabViewFont(WMTabView *tPtr, WMFont *font)
- {
- if (tPtr->font)
- WMReleaseFont(tPtr->font);
-
- tPtr->font = WMRetainFont(font);
- tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
- recalcTabWidth(tPtr);
- }
-
-
- void
- WMSetTabViewItemLabel(WMTabViewItem *item, char *label)
- {
- if (item->label)
- wfree(item->label);
-
- item->label = wstrdup(label);
-
- if (item->tabView)
- recalcTabWidth(item->tabView);
- }
-
-
- char*
- WMGetTabViewItemLabel(WMTabViewItem *item)
- {
- return item->label;
- }
-
-
- void
- WMSetTabViewItemView(WMTabViewItem *item, WMView *view)
- {
- item->view = view;
- }
-
-
- WMView*
- WMGetTabViewItemView(WMTabViewItem *item)
- {
- return item->view;
- }
-
-
- void
- WMDestroyTabViewItem(WMTabViewItem *item)
- {
- if (item->label)
- wfree(item->label);
-
- if (item->view)
- W_DestroyView(item->view);
-
- wfree(item);
- }
-